import { SEO } from '@/utils/seo'
import { FullscreenExitOutlined, FullscreenOutlined } from '@ant-design/icons'
import { request } from '@umijs/max'
import { message, Progress } from 'antd'
import { useEffect, useRef, useState } from 'react'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import Stats from 'three/examples/jsm/libs/stats.module.js'
import styles from './index.less'

// 定义远程全景图 URL
const REMOTE_PANO_URL = `${TENCENT_OSS_URL}/dji_fly_20250131_142248_0066_1738305921186_pano.min.jpg`

const Lab = () => {
  const containerRef = useRef<HTMLDivElement>(null)
  const [isInitialized, setIsInitialized] = useState<boolean>(false)
  const [isFullscreen, setIsFullscreen] = useState<boolean>(false)
  const [downloadProgress, setDownloadProgress] = useState<number>(0)
  const [isDownloading, setIsDownloading] = useState<boolean>(false)
  const animationFrameRef = useRef<number>()
  const sceneRef = useRef<THREE.Scene>()
  const cameraRef = useRef<THREE.PerspectiveCamera>()
  const rendererRef = useRef<THREE.WebGLRenderer>()
  const controlsRef = useRef<OrbitControls>()
  const rotationSpeedRef = useRef<number>(0.0005)
  const statsRefs = useRef<{
    fps: Stats
    memory: Stats
    render: Stats
  }>()

  // 处理全屏切换
  const toggleFullscreen = () => {
    if (!containerRef.current) return

    if (!document.fullscreenElement) {
      containerRef.current.requestFullscreen().catch(() => {
        message.error('全屏切换失败')
      })
    } else {
      document.exitFullscreen()
    }
  }

  // 监听全屏状态变化
  useEffect(() => {
    const handleFullscreenChange = () => {
      setIsFullscreen(!!document.fullscreenElement)
    }

    document.addEventListener('fullscreenchange', handleFullscreenChange)
    return () => {
      document.removeEventListener('fullscreenchange', handleFullscreenChange)
    }
  }, [])

  // 下载图片
  const downloadImage = async (url: string): Promise<string> => {
    setIsDownloading(true)
    setDownloadProgress(0)

    try {
      const response = await request(url, {
        method: 'GET',
        responseType: 'blob',
        getResponse: true,
        onDownloadProgress: (progressEvent) => {
          if (progressEvent.total) {
            const percent = Math.round((progressEvent.loaded / progressEvent.total) * 100)
            setDownloadProgress(percent)
          }
        }
      })

      const blob = response.data
      const localUrl = URL.createObjectURL(blob)
      setIsDownloading(false)
      return localUrl
    } catch (error) {
      setIsDownloading(false)
      message.error('全景图下载失败')
      throw error
    }
  }

  // 加载全景图
  const loadPanorama = (url: string) => {
    if (!sceneRef.current) {
      message.error('场景未初始化')
      return
    }

    // 清除现有全景图
    sceneRef.current.children.forEach((child) => {
      if (child instanceof THREE.Mesh) {
        sceneRef.current?.remove(child)
      }
    })

    // 创建球体几何体
    const geometry = new THREE.SphereGeometry(60, 128, 64)
    geometry.scale(-1, 1, 1)

    // 加载纹理
    const textureLoader = new THREE.TextureLoader()
    textureLoader.load(
      url,
      (texture) => {
        texture.mapping = THREE.EquirectangularReflectionMapping
        texture.colorSpace = THREE.SRGBColorSpace
        texture.minFilter = THREE.LinearMipMapLinearFilter
        texture.anisotropy = 16
        texture.magFilter = THREE.LinearFilter
        texture.generateMipmaps = true

        if (rendererRef.current) {
          rendererRef.current.outputColorSpace = THREE.SRGBColorSpace
          // rendererRef.current.setPixelRatio(Math.min(window.devicePixelRatio, 2))
        }

        const material = new THREE.MeshBasicMaterial({
          map: texture,
          side: THREE.FrontSide,
          toneMapped: true
        })
        const sphere = new THREE.Mesh(geometry, material)
        sceneRef.current?.add(sphere)
      },
      undefined,
      () => {
        message.error('全景图加载失败')
      }
    )
  }

  // 加载远程全景图
  useEffect(() => {
    // 如果场景还没初始化，不执行下载
    if (!isInitialized) return

    const loadRemotePano = async () => {
      try {
        const localUrl = await downloadImage(REMOTE_PANO_URL)
        loadPanorama(localUrl)
      } catch (error) {
        message.error('远程全景图加载失败')
      }
    }

    loadRemotePano()
  }, [isInitialized]) // 依赖项改为 isInitialized

  // 初始化Three.js场景
  useEffect(() => {
    if (!containerRef.current) {
      message.error('容器元素未找到')
      return
    }

    const container = containerRef.current
    const width = container.clientWidth
    const height = container.clientHeight

    // 创建多个Stats面板
    const fpsStats = new Stats()
    fpsStats.showPanel(0) // FPS模式
    fpsStats.dom.style.position = 'absolute'
    fpsStats.dom.style.left = '0px'
    fpsStats.dom.style.top = '0px'
    container.appendChild(fpsStats.dom)

    const memoryStats = new Stats()
    memoryStats.showPanel(1) // 内存模式
    memoryStats.dom.style.position = 'absolute'
    memoryStats.dom.style.left = '80px'
    memoryStats.dom.style.top = '0px'
    container.appendChild(memoryStats.dom)

    const renderStats = new Stats()
    renderStats.showPanel(2) // 自定义面板(ms)
    renderStats.dom.style.position = 'absolute'
    renderStats.dom.style.left = '160px'
    renderStats.dom.style.top = '0px'
    container.appendChild(renderStats.dom)

    // 存储stats引用
    statsRefs.current = {
      fps: fpsStats,
      memory: memoryStats,
      render: renderStats
    }

    // 创建场景
    const newScene = new THREE.Scene()
    sceneRef.current = newScene

    // 添加光源
    newScene.add(new THREE.AmbientLight(0xffffff, 0.3))
    newScene.add(new THREE.DirectionalLight(0xffffff, 0.3))

    // 创建相机
    const newCamera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000)
    newCamera.position.set(0, 0, 0.1)
    cameraRef.current = newCamera

    // 创建渲染器
    const newRenderer = new THREE.WebGLRenderer({
      antialias: true,
      powerPreference: 'high-performance',
      precision: 'highp'
    })
    newRenderer.setSize(width, height)
    newRenderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
    container.appendChild(newRenderer.domElement)
    rendererRef.current = newRenderer

    // 创建控制器
    const controls = new OrbitControls(newCamera, newRenderer.domElement)
    controls.enableZoom = true
    controls.enablePan = false
    controls.enableDamping = true
    controls.rotateSpeed = -0.1
    controls.target.set(0, 0, 0)
    controls.update()
    controlsRef.current = controls

    // 动画循环
    const animate = () => {
      if (statsRefs.current) {
        statsRefs.current.fps.begin()
        statsRefs.current.memory.begin()
        statsRefs.current.render.begin()
      }

      animationFrameRef.current = requestAnimationFrame(animate)

      // 自动旋转
      if (sceneRef.current) {
        sceneRef.current.rotation.y += rotationSpeedRef.current
      }

      if (controlsRef.current) {
        controlsRef.current.update()
      }
      if (rendererRef.current && sceneRef.current && cameraRef.current) {
        rendererRef.current.render(sceneRef.current, cameraRef.current)
      }

      if (statsRefs.current) {
        statsRefs.current.render.end()
        statsRefs.current.memory.end()
        statsRefs.current.fps.end()
      }
    }
    animate()

    // 设置窗口大小变化监听
    const handleResize = () => {
      if (!container) return
      const newWidth = container.clientWidth
      const newHeight = container.clientHeight

      if (cameraRef.current) {
        cameraRef.current.aspect = newWidth / newHeight
        cameraRef.current.updateProjectionMatrix()
      }
      if (rendererRef.current) {
        rendererRef.current.setSize(newWidth, newHeight)
      }
    }
    window.addEventListener('resize', handleResize)

    // 添加键盘控制旋转速度
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'ArrowUp') {
        rotationSpeedRef.current += 0.0005
      } else if (e.key === 'ArrowDown') {
        rotationSpeedRef.current -= 0.0005
      }
      // 限制旋转速度范围
      rotationSpeedRef.current = Math.max(-0.01, Math.min(0.01, rotationSpeedRef.current))
    }
    window.addEventListener('keydown', handleKeyDown)

    setIsInitialized(true) // 设置初始化完成标志

    return () => {
      window.removeEventListener('resize', handleResize)
      window.removeEventListener('keydown', handleKeyDown)
      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current)
      }
      if (controlsRef.current) {
        controlsRef.current.dispose()
      }
      if (container && rendererRef.current) {
        container.removeChild(rendererRef.current.domElement)
        if (statsRefs.current) {
          container.removeChild(statsRefs.current.fps.dom)
          container.removeChild(statsRefs.current.memory.dom)
          container.removeChild(statsRefs.current.render.dom)
        }
      }
      if (rendererRef.current) {
        rendererRef.current.dispose()
      }
    }
  }, []) // 只在组件挂载时执行一次

  // 在React组件中
  useEffect(() => {
    const handleWheel = (e: any) => {
      if (!cameraRef.current) return
      cameraRef.current.fov -= e.deltaY * 0.03 // 调整灵敏度系数‌
      cameraRef.current.fov = THREE.MathUtils.clamp(cameraRef.current.fov, 20, 80) // 限制视野范围‌
      cameraRef.current.updateProjectionMatrix()
    }

    // 添加触摸事件处理
    let touchStartDistance = 0
    let initialFov = 0

    const handleTouchStart = (e: TouchEvent) => {
      if (e.touches.length === 2) {
        const touch1 = e.touches[0]
        const touch2 = e.touches[1]
        touchStartDistance = Math.hypot(
          touch2.clientX - touch1.clientX,
          touch2.clientY - touch1.clientY
        )
        if (cameraRef.current) {
          initialFov = cameraRef.current.fov
        }
      }
    }

    const handleTouchMove = (e: TouchEvent) => {
      if (e.touches.length === 2 && cameraRef.current) {
        const touch1 = e.touches[0]
        const touch2 = e.touches[1]
        const currentDistance = Math.hypot(
          touch2.clientX - touch1.clientX,
          touch2.clientY - touch1.clientY
        )

        // 计算缩放比例
        const scale = touchStartDistance / currentDistance
        const newFov = initialFov * scale

        // 限制视野范围
        cameraRef.current.fov = THREE.MathUtils.clamp(newFov, 20, 80)
        cameraRef.current.updateProjectionMatrix()
      }
    }

    if (rendererRef.current?.domElement) {
      rendererRef.current.domElement.addEventListener('wheel', handleWheel, { passive: true })
    }
    window.addEventListener('touchstart', handleTouchStart, { passive: true })
    window.addEventListener('touchmove', handleTouchMove, { passive: true })

    return () => {
      if (rendererRef.current?.domElement) {
        rendererRef.current.domElement.removeEventListener('wheel', handleWheel)
      }
      window.removeEventListener('touchstart', handleTouchStart)
      window.removeEventListener('touchmove', handleTouchMove)
    }
  }, [cameraRef])

  return (
    <>
      <SEO
        title="实验室 - Zusheng Studio"
        description="Zusheng Studio的实验室，用于研究和展示各种前沿技术和创意实验。"
        keywords="Zusheng,实验室,技术研究,创意实验,Three.js,WebGL,全景图"
        url="https://zusheng.cc/lab"
      />
      <div className={styles.pageLab + ' page'}>
        <div ref={containerRef} className={styles.container}>
          {isDownloading && (
            <div className={styles.loadingContainer}>
              <Progress
                type="circle"
                percent={downloadProgress}
                size={'small'}
                strokeColor={{
                  '0%': '#108ee9',
                  '100%': '#87d068'
                }}
                format={(percent) => `${percent}%`}
              />
            </div>
          )}
          <button
            type="button"
            className={styles.fullscreenButton}
            onClick={toggleFullscreen}
            title={isFullscreen ? '退出全屏' : '全屏显示'}
          >
            {isFullscreen ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
          </button>
        </div>
      </div>
    </>
  )
}

export default Lab
